//package tools;
//
//
//import com.fasterxml.jackson.databind.DeserializationFeature;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.jayway.jsonpath.Configuration;
//import com.jayway.jsonpath.DocumentContext;
//import com.jayway.jsonpath.JsonPath;
//import com.jayway.jsonpath.ParseContext;
//import com.jayway.jsonpath.TypeRef;
//import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
//import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
//import lombok.NonNull;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.jetbrains.annotations.Nullable;
//
//import java.lang.reflect.ParameterizedType;
//import java.lang.reflect.Type;
//import java.util.List;
//import java.util.Map;
//
//import static com.jayway.jsonpath.Option.DEFAULT_PATH_LEAF_TO_NULL;
//import static com.jayway.jsonpath.Option.SUPPRESS_EXCEPTIONS;
//import static java.util.Objects.isNull;
//import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
//import static org.springframework.core.ResolvableType.forClassWithGenerics;
//
///**
// * @author hupeng.net@hotmail.com
// */
//@Slf4j
//public final class JsonPathUtils {
//    private static ParseContext jsonPath;
//
//    static {
//        ObjectMapper objectMapper = BeanObjectMapper
//            .create(JsonPathUtils::initContext)
//            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//        initContext(objectMapper);
//    }
//
//    private static void initContext(ObjectMapper m) {
//        log.info("init JsonPathUtils");
//        Configuration conf = Configuration
//            .defaultConfiguration()
//            .jsonProvider(new JacksonJsonProvider(m))
//            .mappingProvider(new JacksonMappingProvider(m))
//            .addOptions(DEFAULT_PATH_LEAF_TO_NULL, SUPPRESS_EXCEPTIONS);
//        m.registerModule(new NamedEnumModule());
//        jsonPath = JsonPath.using(conf);
//    }
//
//    public static DocumentContext parseJson(String json) {
//        json = StringUtils.defaultIfBlank(json, "{}");
//        return jsonPath.parse(json);
//    }
//
//    public static DocumentContext parseObject(Object object) {
//        if (isNull(object)) {
//            return jsonPath.parse("{}");
//        }
//        if (object instanceof Map) {
//            return jsonPath.parse(object);
//        }
//        if (object instanceof Iterable) {
//            return jsonPath.parse(toJsonString(object));
//        }
//        return jsonPath.parse(toMap(object));
//    }
//
//    @SuppressWarnings("unchecked")
//    public static <T> List<T> readList(DocumentContext context, String path, Class<T> itemClass) {
//        ResolvableListTypeRef typeRef = new ResolvableListTypeRef(itemClass);
//        return (List<T>) context.read(path, typeRef);
//    }
//
//    @SuppressWarnings("unchecked")
//    public static <T> Map<String, T> readMap(DocumentContext context, String path, Class<T> valueClass) {
//        ResolvableMapTypeRef typeRef = new ResolvableMapTypeRef(valueClass);
//        return (Map<String, T>) context.read(path, typeRef);
//    }
//
//    public static <T> List<T> readList(String json, String path, Class<T> itemClass) {
//        return readList(parseJson(json), path, itemClass);
//    }
//
//    public static <T> List<T> readList(Object pojo, String path, Class<T> itemClass) {
//        return readList(parseObject(pojo), path, itemClass);
//    }
//
//    public static <T> T read(String json, String path) {
//        return parseJson(json).read(path);
//    }
//
//    public static <T> T read(@NonNull DocumentContext doc, String path) {
//        return doc.read(path);
//    }
//
//    public static <T> T readObject(Object object, String path) {
//        return parseObject(object).read(path);
//    }
//
//    public static <T> T readObject(@NonNull Object json, String path, Class<T> itemClass) {
//        return parseObject(json).read(path, itemClass);
//    }
//
//    public static <T> T read(String json, String path, Class<T> itemClass) {
//        return parseJson(json).read(path, itemClass);
//    }
//
//    public static <T> T read(@NonNull DocumentContext doc, String path, Class<T> itemClass) {
//        return doc.read(path, itemClass);
//    }
//
//    public static Object read(String json, String path, ParameterizedType type) {
//        return parseJson(json).read(path, new TypeRefWrapper(type));
//    }
//
//    @Nullable
//    public static String readAsString(String json, String path) {
//        Object value = read(json, path);
//        return ifInstanceOf(value, String.class, v -> (String) v)
//            .orElseNotNull(Object::toString)
//            .value();
//    }
//
//    @Nullable
//    public static String readAsString(Object json, String path) {
//        Object value = readObject(json, path);
//        return ifInstanceOf(value, String.class, v -> (String) v)
//            .orElseNotNull(Object::toString)
//            .value();
//    }
//
//    @Nullable
//    public static String readAsString(DocumentContext doc, String path) {
//        Object value = read(doc, path);
//        return ifInstanceOf(value, String.class, v -> (String) v)
//            .orElseNotNull(Object::toString)
//            .value();
//    }
//
//    public static String readAsString(DocumentContext doc, String path, String defaultValue) {
//        String r = readAsString(doc, path);
//        return defaultIfNull(r, defaultValue);
//    }
//
//    private JsonPathUtils() {
//
//    }
//
//    static class ResolvableListTypeRef extends TypeRef<ResolvableListTypeRef> {
//        private Type dynType;
//
//        ResolvableListTypeRef(Class<?> type) {
//            this.dynType = forClassWithGenerics(List.class, type)
//                .getType();
//        }
//
//        @Override
//        public Type getType() {
//            return this.dynType;
//        }
//    }
//
//    public static class ResolvableMapTypeRef extends TypeRef<ResolvableMapTypeRef> {
//        private Type dynType;
//
//        ResolvableMapTypeRef(Class<?> type) {
//            this.dynType = forClassWithGenerics(Map.class, String.class, type)
//                .getType();
//        }
//
//        @Override
//        public Type getType() {
//            return this.dynType;
//        }
//    }
//
//    static class TypeRefWrapper extends TypeRef<TypeRefWrapper> {
//        private Type type;
//
//        TypeRefWrapper(ParameterizedType type) {
//            this.type = type;
//        }
//
//        @Override
//        public Type getType() {
//            return type;
//        }
//    }
//
//}
